package com.tedu.api.io;

import org.junit.Test;

import java.io.*;
import java.nio.charset.StandardCharsets;

/**
 * 标准IO流-----目的：数据传输 输出文本，图片
 * java定义一套标准流-->数据传输--->创建流：直接创建某个流对象
 * 标准流规则①：方向划分---输入流和输出流
 *           输入流 读入--->文件--->相当于程序--->文件往程序走
 *           InputStream(抽象类：定义所有读的写法)【学习：子实现类】
 *           输出流：写出--->文件--->相当于程序--->程序写出
 *  *           InputStream(抽象类：定义所有写的方法)【学习：子实现类】
 *          ②：功能划分
 *          低级流【节点流】：是建立在程序与数据源之间的"管道流"
 *                  功能：负责搬运的数据点，输入流于输出流都有自己的 低级流
 *                  特点:一个字节一个字节读或者写的方法
 *          FileOutputSteam 低级流继承InputSteam---文件传输流：写
 *          FileInputSteam 低级流继承OutputSteam---文件传输流：读
 *          高级流【处理流】：不能直接创建对象，不能独立存在
 *               功能：专门处理低级流以及其他高级流的流
 *               特点：搬运数据时，实现具体功能，效率提高流
 *   ----总结:输入流和输出流，具备功能，低级流与高级流
 *   实际使用：明确使用具体流，每个流都有自己功能
 */
public class IOAPI {
    /**
     * 文件输出流
     * 输入流     低级流---
     * 标准流    方向    功能：       文件输出流：FileOutputSteam
     * 输出流     高级流
     * 需求：写一个文件fos.txt
     * FileOutputStream 构造器使用
     * new FileOutputStream("路径+文件全称")
     * new FileOutputStream("路径+文件全称"，boolean append)
     * 写出文件的同时实现追加效果，第二个参数：true  追加
     * false  默认不追加
     * new FileOutputStream(File file,boolean append)
     */
    @Test
    public void testFOS() {
        FileOutputStream fos=null;
        //低级流--文件输出流对象---从程序中写出”文件：数据“
        try {
            fos = new FileOutputStream("fos.txt", true);
            //需求：fos.txt 增加一行文本
            String say = "玛卡巴卡";
            //字符串由字符数组组成--数组的功能--getBytes()转换为字节数组
            //输出流---写功能：write(byte[] b) 写出字节数组
            fos.write(say.getBytes("UTF8"));
            //必须关闭流---目的：节省内存开销
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch(IOException e){
            e.printStackTrace();
        }finally {
            if(fos!=null)
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
        }

    }

    /**
     * 文件输入流：读入操作
     * FileInputStream  文件输入流
     * read()  返回一个读取一个字节----效率低
     * read(字节数组byte[] b)
     * 返回一个”指定字节数组：空间大小“的读取---效率高
     * 需求；读入fos.txt文件内容
     */
    @Test
    public void testFIS(){
        FileInputStream fis=null;
        //创建文件输入流---读入:fos.txt
        try {
            fis = new FileInputStream("fos.txt");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }

        //读入效率高：创建字节数组-指定空间为：10KB
        byte[] data = new byte[1024 * 10];
        //读入操作：read(字节数组)
        int len = 0;
        try {
            len = fis.read(data);
        } catch (IOException e) {
            e.printStackTrace();
        }
        //写出：文本----字符串--针对流操作，提供构造器
        //                    文件按照”指定字节数组空间“写入程序中
        //                    从0开始写入程序，写入到-1结束
        //                    len：十进制转换为二进制，写入，不等-1，一直写入
        //一次性将给定数据按照字节指定空间大小，写出成字符串
        String str = new String(data, 0, len);
        System.out.println("打印Fos.txt文件" + str);
    }

         /**
         * 需求：利用标准流实现视频复制粘贴
         */
        @Test
        public void testCV () {
            FileInputStream fis=null;
            FileOutputStream fos=null;
            //1.从”复制文件.mp4“ 复制 操作---读入
            try {
                fis = new FileInputStream("复制文件.mp4");
                //2.创建新文件"新文件.mp4"粘贴 操作---写出
                fos = new FileOutputStream("新文件.mp4");
                //3.保存每次读取的数据【字节量---int】
                int len = -1;
                //4.一直从”复制文件.mp4“进入读入操作，不等于-1 一直读
                //(len=fis.read())!=-1

                while ((len = fis.read()) != -1) {//true
                    //4.1同时 写出”新文件.mp4“
                    fos.write(len);
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                //5.关闭流  -----测：效率低--正常播放

                try {
                    if(fis!=null);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            }


        /**
         * 需求：利用标准流实现视频复制粘贴--效率低
         *                              效率高--->空间执行为：自定 100KB
         *
         *【高级流】BufferedInputStream 缓冲输入流---提高效率--缓冲区:字节数组【长度按照文件大小合理分配】
         *        BufferedOutputStream缓冲输出流--提高效率--缓冲区:字节数组【长度按照文件大小合理分配】
         * 高级流使用方式:①处理低级流，套在低级流上
         *              写法:new 高级流(传入低级流使用)
         *              ②直接使用高级流的方法
         *              ③高级流不能直接创建【不能独立存在】
         */
        @Test
        public void testCVS (){
            FileInputStream fis=null;
            BufferedInputStream bis=null;
            FileOutputStream fos=null;
            BufferedOutputStream bos=null;
            //创建低级流：读入”复制文件.mp4“
            try {
                fis =
                       new FileInputStream("复制文件.mp4");
                //创建高级流：套在低级流上【自动缓冲组：字节数组】
                bis = new BufferedInputStream(fis);
                //2.创建低级流：写出”高效视频.mp4“
                fos =
                        new FileOutputStream("高效文件.mp4");
                //2.创建高级流：套在低级流上【自动缓冲组：字节数组】
                bos = new BufferedOutputStream(fos);
                //3.保存数据
                int len = -1;
                //4.高级流---低级流方法一致---read()读取内嵌缓冲区【字节数组】
                //高级流---低级流方法一致---read()写出内嵌缓冲区【字节数组】
                //一直从”复制文件.mp4“读取数据，不等于-1，一直读
                //(bis.read())!=-1
                long start = System.currentTimeMillis();
                while ((len = bis.read()) != -1) {
                    bos.write(len);
                }
                long end = System.currentTimeMillis();
                System.out.println("复制粘贴花费多少：" + (end - start) + "毫秒数");

            } catch (IOException e) {
                e.printStackTrace();
            } finally {

                //关闭流---高级流与低级流：都关--->高级流间接性关闭低级流-->关闭高级流
                {
                    try {
                        bis.close();//高级流---缓冲输入流
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                try {
                    bos.close();//高级流---缓冲输出流
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }
        /**
         * 高级流----缓冲流【内嵌缓冲区】
         * BufferedOutputStream   缓冲输出流
         *
         *
         * 需求：通过缓冲输出流实现从程序写出文件：bos.txt,写出内容
         */
        @Test
        public void testBOS (){
            FileOutputStream fos=null;
            BufferedOutputStream bos=null;
            //1.创建低级流-->bos.txt
            try {
                fos = new FileOutputStream("bos.txt");
                //2.创建高级流--->缓冲区：字节数组---合理【传输效率高】
                bos = new BufferedOutputStream(fos);
                //3.写出文本内容
                String str = "玛卡巴卡";
                //4.写出到bos.txt文件中：字符串转成字节数组--写出
                bos.write(str.getBytes());
                //5.将缓冲区数据一次性写出 flush() 【立即写出】
                //bos.flush();

            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    bos.close();//关闭流---一定把缓冲流数据全部写出
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        /**
         *
         */
        @Test
        public void testBOSIO () {
            //1.置空流---提示所有流作用域：使用范围
            FileOutputStream fos = null; //低级流：搬运数据
            BufferedOutputStream bos = null; //高级流：缓冲输出流
            //2.捕获流异常并且做出处理
            try {
                fos = new FileOutputStream("bos.txt");//低级流
                bos = new BufferedOutputStream(fos);//高级流：缓冲区：字节数
                bos.write("玛卡巴卡".getBytes());
                bos.flush();
            } catch (FileNotFoundException e) {//IO流”小“异常
                e.printStackTrace();
            } catch (IOException e) { //IO流”中“异常：小异常父类
                e.printStackTrace();
            } catch (Exception e) {//"大"异常  Exception
                e.printStackTrace();
            } finally {//一定执行代码块
                //3.关闭流---高级流--释放资源
                //判断：高级流一定是不为null，关闭
                if (bos != null)
                    try {
                        bos.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
            }
        }
    }


